class DropBox{
  int BOXSIZE = 20;  //10 elements/lines
  
  String actors[] = loadStrings("allWebSites.txt");
  ArrayList current; //contain all strings that matches current user input
  
  boolean selected = false;  //true if user choose an item from droplist
  boolean input = false; //true if user giving input in dropmenu

  String currentType = "";  //contain string that is typed by user
  String selectedStr = "";  //contain string that user selected finally
  
  PVector locV;
  PVector sizeV;
 
  boolean drawCursor = true;  //used for cursor blinking effect
  
  float rectSize; //size of dropbox
  
  int scrollbarWidth = 15;
  int scrollbarHeight;
  int startIndexFromScroll;
  
  float sposY;
  int minScrollerSize = 5; 

  boolean scrollNeeded = false;  //used for setting the size of dropbox to max if scroll needed or smaller size if not needed

  DropBox(float x, float y, float w){
    locV = new PVector(x, y);
    sizeV = new PVector(w, 0);
    
    current = new ArrayList();
    sposY = locV.y;
  }

  void setLocation(PVector locV){
    this.locV = locV;
  }

  PVector getLocation(){
    return locV;
  }
  
  PVector getSize(){
    return sizeV;  
  }

  String getSelectedString(){
    return selectedStr;
  }  
  
  void render(){
//    pushStyle();    
    fill(GUI_FILL_COLOR, GUI_TRANSPARENTCY);
    stroke(70);
    strokeWeight(1);
    
    sizeV.y = FONT_SIZE*current.size();
    rect(locV.x, locV.y-FONT_SIZE-4, sizeV.x, FONT_SIZE+2);  //input box
    
    if(current.size()>BOXSIZE){ //scroll needed
      rectSize = BOXSIZE*FONT_SIZE;
      scrollNeeded = true;
    }else{
      rectSize = sizeV.y;
      scrollNeeded = false;
    }
  
    if(current.size()>0){  
      rect(locV.x, locV.y, sizeV.x, rectSize);  //dropbox
      if(scrollNeeded){
        scrollbarHeight = max(minScrollerSize, round(rectSize/(current.size()-BOXSIZE)));
        rect(locV.x+sizeV.x-scrollbarWidth, locV.y, scrollbarWidth, rectSize); //scrollbox
//        pushStyle();
        fill(80);
        rect(locV.x+sizeV.x+1-scrollbarWidth, sposY, scrollbarWidth-2, scrollbarHeight); //scroller
//        popStyle();
      }
    }
   
    //cursor blinking
    if(frameCount%30 == 0){
      if(drawCursor == true){
         drawCursor = false;
      }else{ 
         drawCursor = true;
      }
    }   
    //draw the cursor
    if(input && drawCursor){
//      pushStyle();
      stroke(255);
      line(locV.x+2+textWidth(currentType), locV.y-FONT_SIZE-2, locV.x+2+textWidth(currentType), locV.y-4 );   
//      popStyle();     
    }
   
    textAlign(LEFT);
    textSize(FONT_SIZE);
    fill( TEXT_FILL_COLOR );
    
    //draw user input if in input mode or final seleted string if in selected mode in the input box
    if(selected)
      text(selectedStr, locV.x+2, locV.y-4 );
    else
      text(currentType, locV.x+2, locV.y-4 );
    
    //draw all matched strings in the dropbox 
    if(scrollNeeded){
      int upto = min((int)(rectSize/FONT_SIZE), current.size());
      for(int i = 0; i<upto; i++){
        startIndexFromScroll = (int) map( (sposY-locV.y), 0, rectSize-scrollbarHeight, 0, current.size()-BOXSIZE+1 );
        text(String.valueOf(current.get(i+startIndexFromScroll)), locV.x+2, locV.y+(i+1)*FONT_SIZE );
      }
    }else{
      for(int i = 0; i<current.size(); i++){
        text(String.valueOf(current.get(i)), locV.x+2, locV.y+(i+1)*FONT_SIZE );   
      }
    }
    
    /*for(int i = startIndexFromScroll; i<current.size(); i++){
      //println("index = "+(i+startIndexFromScroll));
      text(String.valueOf(current.get(i)), locV.x+2, locV.y+(i+1-startIndexFromScroll)*FONT_SIZE );
    }*/
    
    
    //draw the box at selection
    if((mouseX > locV.x && mouseX < (locV.x+sizeV.x)) && (mouseY > locV.y && mouseY < (locV.y+rectSize)) && !scrollNeeded){
      int index = (int)(mouseY-locV.y)/FONT_SIZE;
//      pushStyle();
      fill(150,150,255,128);
      rect(locV.x, (index)*FONT_SIZE+locV.y, sizeV.x, FONT_SIZE);
//      popStyle();
    }else if((mouseX > locV.x && mouseX < (locV.x+sizeV.x-scrollbarWidth)) && (mouseY > locV.y && mouseY < (locV.y+rectSize)) && scrollNeeded){
      int index = (int)(mouseY-locV.y)/FONT_SIZE;
//      pushStyle();
      fill(150,150,255,128);
      rect(locV.x, (index)*FONT_SIZE+locV.y, sizeV.x-scrollbarWidth, FONT_SIZE);
//      popStyle();
    }

    
    //get scroller location
    if((mouseX > locV.x+sizeV.x-scrollbarWidth && mouseX < locV.x+sizeV.x) && (mouseY > locV.y && mouseY < (locV.y+rectSize-scrollbarHeight)) && mousePressed){
      if(scrollNeeded){
        //startIndexFromScroll = (int) map( (mouseY-locV.y), 0, rectSize, 0, current.size()-BOXSIZE+1 );
        sposY = mouseY;
      }
    }
    
//    popStyle();
  }
  
  
  void processKey(){
    if(input == true){ //listen to user keyboard input only if in input mode
      if(key == BACKSPACE && currentType.length() > 0){
        currentType = currentType.substring(0, currentType.length()-1);
        current.clear();
        updateCurrentArrayList();
      }else if((( key >= '0' ) && ( key <= '9' )) || (( key >= 'a' ) && ( key <='z' )) || (( key >= 'A' ) && ( key <='Z' )) || ( key == 32 ) || ( key == 45 ) || (key == '.')){
        currentType += key;
        current.clear();
        updateCurrentArrayList();
        sposY = locV.y;
        if(current.size() == 1){
          selected = true;
          input = false;
          selectedStr = String.valueOf(current.get(0));
//          println(selectedStr); 
          current.clear();
          currentType = "";
          sizeV.y = 0;
          rectSize = 0;
        }
      }
    }
  }
  
  
  void updateCurrentArrayList(){
    //avoid smaller sized strings that are less sized than the string given by user to avoid arrayOutOfBoundExeption  
    for(int i=0; i<actors.length; i++){
      if(actors[i].length() < currentType.length()){
        continue;
      }
      //currentType.length()>=1 is checked because otherwise comparing with substring of length 0 results in true
      if(currentType.length()>=1 && currentType.compareToIgnoreCase(actors[i].substring(0,currentType.length())) == 0){
        current.add(actors[i]);
      }
    }
  }
  
  
  void processClick(){
    //check if the user clicked in the input box
    if((mouseX > locV.x && mouseX < (locV.x+sizeV.x)) && (mouseY > locV.y-FONT_SIZE-4 && mouseY < (locV.y-2))){
      input = true;
      if(selected)
        currentType = selectedStr;
      selected = false;
      //currentType = selectedStr;
      //selectedStr = "";
      current.clear();
      updateCurrentArrayList();
    //check if the user clicked any item from dropbox  
    }else if((mouseX > locV.x && mouseX < (locV.x+sizeV.x)) && (mouseY > locV.y && mouseY < (locV.y+rectSize))){
      selected = true;
      input = false;
      int index = (int)(mouseY-locV.y)/FONT_SIZE;
      if(scrollNeeded){
        selectedStr = String.valueOf(current.get(index+startIndexFromScroll));
        //println(selectedStr);
        vm.addSite(selectedStr);
      }else{
        selectedStr = String.valueOf(current.get(index));
//        println(selectedStr); 
  vm.addSite(selectedStr);
      }
      current.clear();
      currentType = "";
      sizeV.y = 0;
      rectSize = 0;
    }else{
      //make sure that cursor is not active in multiple input boxex at same time. 
      //Also removes the cursor and input mode when input box is not in focus    
      input = false; 
      //currentType = "";
      rectSize = 0;
      current.clear();
    }
  }
}

